﻿/******************************************************************************
 *  Project:		Neddle Community Edition
 *  Filename:		StringExtensions.cs
 *	Created By:     Kristopher Cargile <kristopher@neddle.org>
 *  Date Created:	March 29, 2011
 * ****************************************************************************
 * IMPORTANT GNU LICENSE INFORMATION. DO NOT REMOVE THIS SECTION!
 * 
 * Neddle :: Copyright (c) 2010-2012, Cargile Technology Group, LLC
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 ******************************************************************************/

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace Neddle
{
    /// <summary>
    /// StringExtensions
    /// </summary>
    public static class StringExtensions
    {
        /// <summary>
        /// Trims a string. If the string is null or empty after being trimmed 
        /// the method return null.
        /// </summary>
        /// <param name="s">the string to trim</param>
        /// <returns>the trimmed string or null</returns>
        public static string TrimOrNull(this string s)
        {
            if (s != null)
            {
                s = s.Trim();
                if (s.Length == 0)
                {
                    s = null;
                }
            }
            return s;
        }

        /// <summary>
        /// Trims a string. If the string is null 
        /// the method return Empty string.
        /// </summary>
        /// <param name="s">the string to trim</param>
        /// <returns>the trimmed string or empty string</returns>
        public static string TrimOrEmpty(this string s)
        {
            s = s != null 
                    ? s.Trim() 
                    : string.Empty;
            return s;
        }

        /// <summary>
        /// Returns true if the string is null or emtpy and optionally
        /// trims the string before testing
        /// </summary>
        /// <param name="s">the string to test</param>
        /// <returns>true if the string is null or emtpy</returns>
        public static bool IsNullOrEmptyTrimmed(this string s)
        {
            return String.IsNullOrEmpty((s != null) ? s.Trim() : s);
        }

        /// <summary>
        /// Checks parameter for null and throws <code>ArgumentNullException</code> if null.
        /// </summary>
        /// <param name="parm">the parameter to check for null</param>
        /// <exception cref="ArgumentNullException">parm is null</exception>
        public static void CheckNullOrEmpty(this string parm)
        {
            parm.CheckNull(null);
        }

        /// <summary>
        /// Checks parameter for null and throws <code>ArgumentNullException</code> if null.
        /// </summary>
        /// <param name="parm">the parameter to check for null</param>
        /// <param name="parmName">the _name of the parameter</param>
        /// <exception cref="ArgumentNullException">parm is null</exception>
        public static void CheckNullOrEmpty(this string parm, string parmName)
        {
            if (parm == null)
            {
                throw new ArgumentNullException(parmName);
            }
            if (parm.IsNullOrEmptyTrimmed())
            {
                throw new ArgumentException("Value cannot be empty.", parmName);
            }
        }


        /// <summary>
        /// Converts the specified text to an object 
        /// </summary>
        /// <typeparam name="T">the type to convert to</typeparam>
        /// <param name="value">specified text</param>
        /// <returns>An Object that represents the converted text.</returns>
        /// <exception cref="ArgumentNullException">type is null</exception>
        public static T ConvertToTypeOrDefault<T>(this string value)
        {
            return value.ConvertToTypeOrDefault(default(T));
        }

        /// <summary>
        /// Converts the specified text to an object
        /// </summary>
        /// <typeparam name="T">the type to convert to</typeparam>
        /// <param name="value">specified text</param>
        /// <param name="defaultValue">default value if conversion fails</param>
        /// <returns>
        /// An Object that represents the converted text.
        /// </returns>
        /// <exception cref="ArgumentNullException">type is null</exception>
        public static T ConvertToTypeOrDefault<T>(this string value, T defaultValue)
        {
            T retVal = defaultValue;
            if (!String.IsNullOrEmpty(value))
            {
                try
                {
                    TypeConverter typeConverter = TypeDescriptor.GetConverter(typeof(T));
                    if (typeConverter.CanConvertFrom(typeof(String)))
                    {
                        retVal =  (T) typeConverter.ConvertFromString(value);
                    }
                    else
                    {
                        throw new NotSupportedException("Can't convert from string");
                    }
                }
                catch (Exception)
                {
                }
            }

            return retVal;
        }

        /// <summary>
        /// Determines whether the specified value is GUID.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="guid">The GUID.</param>
        /// <returns>
        /// 	<c>true</c> if the specified value is GUID; otherwise, <c>false</c>.
        /// </returns>
		public static bool IsGuid(this string value, out Guid guid)
		{
			bool isValid = false;
			guid = Guid.Empty;
			if (!String.IsNullOrEmpty(value))
			{
				Regex isGuid = new Regex(@"^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$", RegexOptions.Compiled);
				if (isGuid.IsMatch(value))
				{
					guid = new Guid(value);
					isValid = true;
				}
			}

			return isValid;
		}
    }
}
